#include "FontPix.h"

#include "../common/com_mem.h"
#include "../common/com_console.h"
#include "../sys/gl.h"

#include <stdio.h>

#define ADDPOS_X(x) glBitmap(0,0,0,0,x,0,NULL)
#define ADDPOS_Y(y) glBitmap(0,0,0,0,0,y,NULL)

CFontPix::CFontPix()
{
	g_allocv(m_tempBuf, char, 16384);

	for (int i=FIRST_CHAR;i<LAST_CHAR;i++)
		m_charData[i-FIRST_CHAR].data = NULL;

	m_fontLoaded = false;
	int p=0;
	for (int i=0;i<2;i++)
		for (int j=0;j<2;j++)
			for (int k=0;k<2;k++)
				setColor3fc(p++,(float)i,(float)j,(float)k);
}

CFontPix::~CFontPix()
{
	g_freev(m_tempBuf);
	killFont();
}

void CFontPix::killFont()
{
	for (int i=FIRST_CHAR;i<LAST_CHAR;i++)
		g_freev(m_charData[i-FIRST_CHAR].data);

	m_fontLoaded = false;
}

bool CFontPix::load(char *fname, int fontSize)
{
	FILE *f = fopen(fname,"rb");
	if (!f)
		return false;

	fseek(f,0,SEEK_END);
	int len = ftell(f);
	fseek(f,0,SEEK_SET);

	gByte *data;
	g_allocv(data,gByte,len);
	fread(data,len,1,f);
	fclose(f);
	
	bool r = load(data,len,fontSize);
	g_free(data);

	return r;
}

bool CFontPix::load(void *data, int dataSize, int fontSize)
{
	int error;
	FT_Library library;
	FT_Face face;

	if (m_fontLoaded)
		killFont();

	if (error=FT_Init_FreeType( &library ))
	{
		com_error("Could not load font library. ErrNo=%d",error);
		return false;
	}

	error = FT_New_Memory_Face(library,(FT_Byte*)data,dataSize,0,&face);
	if (error)
	{
		com_error("Could not load font data. ErrNo=%d",error);
		return false;
	}

	error = FT_Set_Char_Size(face,0,fontSize*64,96,96);
	if (error)
	{
		com_error("Could not set char size. ErrNo=%d",error);
		return false;
	}

	for (int c=0;c<LAST_CHAR-FIRST_CHAR;c++)
	{
		FT_UInt gIndex = FT_Get_Char_Index(face, c+FIRST_CHAR);

		error=FT_Load_Glyph(face, gIndex, FT_LOAD_DEFAULT);
		if (error)
		{
			com_error("Could not load char %d. ErrNo=%d",c, error);
			continue;
		}

		error=FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);

		if (error)
		{
			com_error("Could not render char %d. ErrNo=%d",c,error);
			continue;
		}


		m_charData[c].width = face->glyph->bitmap.width;
		m_charData[c].height = face->glyph->bitmap.rows;
		m_charData[c].advanceX = face->glyph->advance.x;
		m_charData[c].advanceY = face->glyph->advance.y;
		m_charData[c].coordX = face->glyph->bitmap_left;
		m_charData[c].coordY = face->glyph->bitmap_top - face->glyph->bitmap.rows;

		g_allocv(m_charData[c].data, gByte, 2*m_charData[c].width*m_charData[c].height);

		int p1=0,p2;
		for (int i=0;i<m_charData[c].height;i++)
		{
			p2=(m_charData[c].height-i-1)*m_charData[c].width;
			for (int j=0;j<m_charData[c].width;j++)
			{
				m_charData[c].data[p1++] = 255;
				m_charData[c].data[p1++] = face->glyph->bitmap.buffer[p2++];
			}
		}	
	}

	FT_Done_Face(face);
	FT_Done_FreeType(library);

	m_fontLoaded = true;
	return true;
}

void CFontPix::startRender(int width, int height)
{
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glOrtho(0,width,height,0,-1,1);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();

	glPushAttrib(GL_CURRENT_BIT | GL_PIXEL_MODE_BIT | GL_ENABLE_BIT);
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);
	glDisable(GL_LIGHTING);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glPixelStorei(GL_UNPACK_ALIGNMENT ,1);
}

void CFontPix::endRender()
{
	glPopAttrib();

	glMatrixMode(GL_PROJECTION);
	glPopMatrix();		
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();		
}

void CFontPix::setColor(int color)
{
	if ((color>=0)&&(color<MAX_COLORS))
		setColor4f(m_colors[color][0],m_colors[color][1],m_colors[color][2],m_colors[color][3]);
}

void CFontPix::setColor3f(float red, float green, float blue)
{
	setColor4f(red, green, blue,1.0f);
}

void CFontPix::setColor4f(float red, float green, float blue, float alpha)
{
	glPixelTransferf(GL_RED_SCALE,red);
	glPixelTransferf(GL_GREEN_SCALE,green);
	glPixelTransferf(GL_BLUE_SCALE,blue);
	glPixelTransferf(GL_ALPHA_SCALE,alpha);
}

void CFontPix::setColor3fc(int color, float red, float green, float blue)
{
	setColor4fc(color, red, green, blue, 1.0f);
}

void CFontPix::setColor4fc(int color, float red, float green, float blue, float alpha)
{
	if ((color>=0)&&(color<MAX_COLORS))
	{
		m_colors[color][0] = red;
		m_colors[color][1] = green;
		m_colors[color][2] = blue;
		m_colors[color][3] = alpha;
	}
}

void CFontPix::moveTo(int x, int y)
{
	m_currentX = x;
	m_currentY = y;
	glRasterPos2d(m_currentX, m_currentY);
}

void CFontPix::moveRel(int x, int y)
{
	m_currentX += x;
	m_currentY += y;
	glRasterPos2d(m_currentX, m_currentY);
}

void CFontPix::print(char *str)
{
	for (int i=0;str[i];i++)
	{
		if ((str[i]=='\\')&&(str[i+1]=='c'))
		{
			i+=2;
			if ((str[i]>='0')&&(str[i]<='0'+MAX_COLORS))
			{
				setColor(str[i]-'0');
			}
		}
		else
		if ((str[i]>=FIRST_CHAR)&&(str[i]<LAST_CHAR))
		{
			int p=str[i]-FIRST_CHAR;
			moveRel(m_charData[p].coordX, -m_charData[p].coordY);
			glDrawPixels(m_charData[p].width, m_charData[p].height,GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, m_charData[p].data);
			moveRel((m_charData[p].advanceX>>6)-m_charData[p].coordX,m_charData[p].coordY);
		}
	}
}

void CFontPix::print(int width, int align, char *str)
{
	int oldX = m_currentX;
}


void CFontPix::printf(char *fmt, ...)
{
}

void CFontPix::printf(int width, int align, char *fmt, ...)
{
}

int CFontPix::getTextWidth(char *str)
{
	return 0;
}

int CFontPix::getTextHeight(char *str)
{
	return 0;
}
